#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdlib.h>

#include "commu.h"

#define SERIAL_PORT_DEVICE "/data/local/tmp/socatpty1"

// 打开串口
int open_serial_port(const char *port) {
    int fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1) {
        perror("无法打开串口");
        return -1;
    }

    // 配置串口参数
    struct termios options;
    tcgetattr(fd, &options);
    cfsetospeed(&options, B460800); // 波特率 460800
    cfsetispeed(&options, B460800);
    options.c_cflag |= (CLOCAL | CREAD); // 本地连接和启用接收
    options.c_cflag &= ~PARENB; // 无校验位
    options.c_cflag &= ~CSTOPB; // 1 位停止位
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8; // 8 位数据位
    tcsetattr(fd, TCSANOW, &options);

    return fd;
}

short check_sum(u8 *buf, int len)
{
	short sum = 0;

	while (len--)
		sum += *buf++;

	return sum;
}

static int prepare_one_pack(P_commu_pack p_commu_pack, u8 cmd, u8 subcmd, char* buf, int buf_len)
{
    short crc = 0;

    p_commu_pack->head[0] = PACK_CMD_HEAD_0;
    p_commu_pack->head[1] = PACK_CMD_HEAD_1;

    p_commu_pack->cmd[0] = cmd;
    p_commu_pack->cmd[1] = subcmd;

    memcpy(p_commu_pack->buff, buf, buf_len);
    p_commu_pack->data_len = buf_len;
    p_commu_pack->data_len += CRC_LEN;

    crc = check_sum((u8*)p_commu_pack, p_commu_pack->data_len + COM_HEAD_SIZE - CRC_LEN);

    memcpy(p_commu_pack->buff + buf_len, &crc, CRC_LEN);

    return p_commu_pack->data_len + COM_HEAD_SIZE;
}

P_commu_pack uart_send_and_recv_pack(int fd, u8 cmd, u8 subcmd, char *data, int data_len, int timeout_ms)
{
	int i = 0;
	short pack_len = 0;
	P_commu_pack p_commu_pack = NULL;
    char send_buf[MAX_PACK_SIZE];

	//xSemaphoreTake(p_uart_handle->xMutex, portMAX_DELAY);

	for(i = 0; i < 3; i++)
	{
		p_commu_pack = (P_commu_pack)(send_buf);
		pack_len = prepare_one_pack(p_commu_pack, cmd, subcmd, data, data_len);

        ssize_t bytes_written = write(fd, p_commu_pack, pack_len);
        if (bytes_written < 0) {
            perror("发送数据失败");
            close(fd);
            return NULL;
        }
		usleep(timeout_ms * 1000);
        ssize_t bytes_read = read(fd, p_commu_pack, MAX_PACK_SIZE);
		if(NULL != p_commu_pack)
		{
			//LOG("ver:%s", p_commu_pack->buff);
			printf("recv dat len:%d\n", p_commu_pack->data_len - CRC_LEN);
            // T_andr_real_info *real_info = p_commu_pack->buff;
            // printf("[I2C_CMD_GET_REAL_INFO] sysup_sec:%d cpu_usage:%f gpu_usage:%d cpu_temp:%f gpu_temp:%f mem_usage:%d flash_available:%d\n",
            //     real_info->sysup_sec, real_info->cpu_usage, real_info->gpu_usage, real_info->cpu_temp, real_info->gpu_temp, real_info->mem_usage,
            //     real_info->flash_available);
            break;
		}
	}

	//xSemaphoreGive(p_uart_handle->xMutex);

	//LOG("recv, tic:%u", HAL_GetTick());

	return p_commu_pack;
}

// ip字符串 转 数字
int ip_str_to_value(char *ip)
{
    struct in_addr s;
 
    inet_pton(AF_INET, ip, (void *) &s);
    return s.s_addr;
}

int set_android_ip_addr(int fd, char *ip_addr, char ip_len)
{
	int ret = 0, len = 0;
	P_commu_pack p_commu_pack;

	p_commu_pack = uart_send_and_recv_pack(fd, I2C_CMD_SET_IP_ADDRESS, 0, ip_addr, ip_len, 300);
	if(p_commu_pack != NULL && p_commu_pack->data_len >= CRC_LEN + sizeof(int))
	{
		if((p_commu_pack->data_len - CRC_LEN) < sizeof(int))
			len = p_commu_pack->data_len - CRC_LEN;
		else
			len = sizeof(int);

		memcpy(&ret, p_commu_pack->buff, len);
	}

	return ret;
}

int set_ip_net(int fd, int ip, int gateway, int netMask, int dns)
{
  int ret = 0;
  T_network_config config;

  config.identifier = 14;
  config.ipAddress[0] = ip;
  config.ipAddress[1] = gateway;
  config.ipAddress[2] = netMask;
  config.ipAddress[3] = dns;

  ret = set_android_ip_addr(fd, (char *)&config, sizeof(config));

  return 1;
}

const char *get_filename_without_ext(const char *filepath) {
    // 去除路径部分
    const char *filename = strrchr(filepath, '/');
    if (filename == NULL) {
        filename = filepath; // 如果没有路径，直接使用文件名
    } else {
        filename++; // 跳过 '/'
    }

    // 去除扩展名部分
    char *dot = strrchr(filename, '.');
    if (dot != NULL) {
        // 如果找到扩展名，截断字符串
        *dot = '\0';
    }

    return filename;
}

// 打印帮助信息
void print_help() {
    printf("Usage: ./sender <command> [options]\n");
    printf("Commands:\n");
    printf("  setip    Set IP address\n");
    printf("\nExamples:\n");
    printf("  ./sender setip -i 192.168.10.82 -g 192.168.10.1 -n 255.255.255.0 -d 114.114.114.114\n");
}

// 处理 setip 命令
void handle_setip(int argc, char *argv[]) {
    char *ip = NULL;
    char *gateway = NULL;
    char *netmask = NULL;
    char *dns = NULL;

    // 解析 setip 命令的参数
    int opt;
    while ((opt = getopt(argc, argv, "i:g:n:d:")) != -1) {
        switch (opt) {
            case 'i': // -ip
                ip = optarg;
                break;
            case 'g': // -gateway
                gateway = optarg;
                break;
            case 'n': // -netmask
                netmask = optarg;
                break;
            case 'd': // -dns
                dns = optarg;
                break;
            default:
                print_help();
                exit(EXIT_FAILURE);
        }
    }

    // 检查是否缺少必要参数
    if (ip == NULL || gateway == NULL || netmask == NULL || dns == NULL) {
        print_help();
        exit(EXIT_FAILURE);
    }
    printf("Set ip: ip:%s, gateway: %s, netmask: %s, dns:%s\n", ip, gateway, netmask, dns);

    // 打开串口设备
    int fd = open_serial_port(SERIAL_PORT_DEVICE);
    if (fd == -1) {
        fprintf(stderr, "Failed to open serial port\n");
        exit(EXIT_FAILURE);
    }

    // 设置 IP 地址
    unsigned int ip_int = ip_str_to_value(ip);
    unsigned int gateway_int = ip_str_to_value(gateway);
    unsigned int netmask_int = ip_str_to_value(netmask);
    unsigned int dns_int = ip_str_to_value(dns);

    ip_int = ntohl(ip_int);
    gateway_int = ntohl(gateway_int);
    netmask_int = ntohl(netmask_int);
    dns_int = ntohl(dns_int);

    set_ip_net(fd, ip_int, gateway_int, netmask_int, dns_int);

    // 关闭串口设备
    close(fd);
}

int main(int argc, char *argv[]) {

    if (argc < 2) {
        print_help();
        return 1;
    }

    // 根据子命令调用相应的处理函数
    if (strcmp(argv[1], "setip") == 0) {
        handle_setip(argc, argv);
    } else {
        print_help();
        return 1;
    }

    return 0;
}